#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
#include <fcntl.h>

//#define		HOST	"192.168.50.136"	//服务器打IP地址
//#define		PORT	6666							 //进程端口号，端口号是数字类型
#define		MAX_SIZE		 10*1024	         //缓存容量
int running = 1;
int read_running = 1;
int write_running = 1;

struct client_info
{
	int sockfd;																//客户端的socket标识符fd
	struct	sockaddr_in	client;								//client有关信息
	struct	sockaddr_in	server;							  //server有关信息	
};

/*要执行的客户端读线程函数*/
void	*oneSocketThread_Read(void	*arg)
{
	for(;read_running != 0;)
	{
		char pthread_buffer[MAX_SIZE];
		struct  client_info clientInfo = (struct  client_info)(*((struct  client_info*)arg));		//传入的参数

		int fd = clientInfo.sockfd;																													//客户端的socket标识符
		struct sockaddr_in server = clientInfo.server;																		  //客户端有关的ip/port信息

		bzero(pthread_buffer,MAX_SIZE);
		//确实是否处于连接状态
		if(read(fd,pthread_buffer,sizeof(pthread_buffer))	<=	0)
		{
			printf("服务器端关闭……\n");
			break;
		}
		printf("数据来自服务器端（%s：%d）：%s\n",inet_ntoa(server.sin_addr),ntohs(server.sin_port),pthread_buffer);
	}
	/*退出线程*/
	running = 0;																																		//目的是关闭相应线程，结束程序
	write_running = 0;
	pthread_exit(NULL);
}

/*要执行的客户端写线程函数*/
void	*oneSocketThread_Write(void	*arg)
{
	for (;write_running != 0; )
	{
		char pthread_buffer[MAX_SIZE];
		struct  client_info clientInfo = (struct  client_info)(*((struct  client_info*)arg));		//传入的参数

		int sockfd = clientInfo.sockfd;																										  //已连接的标识符
		struct sockaddr_in client = clientInfo.client;																		   //本地客户端有关的ip/port信息
				
		//printf("键入可以直接发送数据：");
		fgets(pthread_buffer,MAX_SIZE,stdin);
		
		//输入了exit,循环
		if(strncmp(pthread_buffer,"exit",4)	==	0)
		{
			printf("本地客户端关闭……\n");
			break;
		}
		write(sockfd,pthread_buffer,sizeof(pthread_buffer));																		//服务器写
		printf("本地客户端（%s：%d）发送数据：%s\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port),pthread_buffer);
	}
	/*退出线程*/
	read_running = 0;				//running结束while、pthread_read
	running = 0;
	pthread_exit(NULL);
}


int	main(int argc,char* argv[])
{
	int	sockfd,thread_read,thread_write;	 //socket标识符、线程结果
	int server_port;												//服务器的监听端口、ip地址
	char server_ip[16];
	struct	sockaddr_in	server,client;			   //服务器端、客户端信息
	char	buffer[MAX_SIZE];							  //用于保存输入的文本
	unsigned int len_sockaddr;						 //结构体大小
	struct client_info clientInfo;					    //客户端有关的信息
	pthread_t	thread[2];			   					     //线程数组

	len_sockaddr = sizeof(struct sockaddr);	//获取结构体的大小

	if (argc > 1)
	{
		strncpy(server_ip,argv[1],strlen(argv[1]));
		server_port	=	atoi(argv[2]);
		printf("申请连接的服务器地址：%s：%d\n",server_ip,server_port);
	}
	else
	{
		printf("缺少参数，请在./main后输入参数‘申请连接的服务器ip地址、监听端口port’\n");
		exit(1);
	}

	//创建套接字描述符
	if((sockfd	=	socket(AF_INET,SOCK_STREAM,0))	==	-1)
	{
		printf("创建一个通信终端socket失败 \n");
		exit(1);
	}
	printf("创建一个通信终端socket成功\n");
	bzero(&server,sizeof(server));
	server.sin_family	=	AF_INET;
	server.sin_port	=	htons(server_port);
	server.sin_addr.s_addr = inet_addr(server_ip);

	//建立TCP连接
	if(connect(sockfd,(struct	sockaddr *)&server,len_sockaddr)	!= 	0)
	{
		printf("连接服务器失败……\n");
		close(sockfd);
		exit(1);
	}
	printf("连接服务器成功，服务器地址：%s：%d\n",inet_ntoa(server.sin_addr),ntohs(server.sin_port));
	//获取本地地址
	getsockname(sockfd,(struct sockaddr*)&client,&len_sockaddr);																				//打印客户端的本地地址
	printf("客户端本地地址：%s：%d\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port));
	//赋值有关的信息
	clientInfo.sockfd = sockfd;
	clientInfo.server = server;
	clientInfo.client = client;

	//创建客户端的读/写线程，并将已连接套接字标识符作为参数输入
	thread_read = pthread_create(&thread[0],NULL,oneSocketThread_Read,&clientInfo);
	thread_write = pthread_create(&thread[1],NULL,oneSocketThread_Write,&clientInfo);

	printf("客户端可以接收来自服务器的数据，并且键入可以直接发送数据给服务器：\n");
	while(running);
	close(sockfd);		//正常不会运行到这里
	exit(0);
}